﻿using WebTimer.Config;
using WebTimer.ScheduledEvents;
using System;
using System.Threading;
using System.Windows.Forms;
using RJ.Ext;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace WebTimer
{
    public partial class FormMain : Form
    {

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
        /// <summary>   
        /// 得到当前活动的窗口   
        /// </summary>   
        /// <returns></returns>   
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern System.IntPtr GetForegroundWindow();

        static System.Threading.Timer eventTimer;
        private IDictionary<string, CCWin.SkinControl.SkinTextBox> _evs = new Dictionary<string, CCWin.SkinControl.SkinTextBox>();

        public delegate void Action<in T>(T obj);

        public FormMain()
        {
            InitializeComponent();

            InitTab();

            StartTimer();


            //开机启动
            WebTimer.Common.Utils.SetAutoRun(Application.StartupPath + @"\\" + System.IO.Path.GetFileName(Application.ExecutablePath), true);

        }

        /// <summary>
        /// 启动任务线程
        /// </summary>
        private void StartTimer()
        {
            //启动任务线程
            if (eventTimer == null && ScheduleConfigs.GetConfig().Enabled)
            {
                EventManager.RootPath = AppDomain.CurrentDomain.BaseDirectory;
                eventTimer = new System.Threading.Timer(new TimerCallback(ScheduledEventWorkCallback), this, 10000, EventManager.TimerMinutesInterval * 10000);
            }
        }

        /// <summary>
        /// 根据配置文件中的任务创建tab
        /// </summary>
        private void InitTab()
        {
            WebTimer.Config.Event[] events = ScheduleConfigs.GetConfig().Events;
            if (events.IsNotNull()&& events.Length > 0)
            {
                this._evs.Clear();
                tabMonitor.Controls.Clear();
                var i = 0;
                foreach (WebTimer.Config.Event ev in events)
                {
                    TabPage page = new TabPage();
                    page.Text = ev.Key.ToString();
                    page.TabIndex = i;

                    var txtMessage = new CCWin.SkinControl.SkinTextBox();
                    txtMessage.BackColor = System.Drawing.Color.Transparent;
                    txtMessage.DownBack = null;
                    txtMessage.Icon = null;
                    txtMessage.IconIsButton = false;
                    txtMessage.IconMouseState = CCWin.SkinClass.ControlState.Normal;
                    txtMessage.IsPasswordChat = '\0';
                    txtMessage.IsSystemPasswordChar = false;
                    txtMessage.Lines = new string[] {
        "实时日志"};
                    txtMessage.Location = new System.Drawing.Point(3, 3);
                    txtMessage.Margin = new System.Windows.Forms.Padding(0);
                    txtMessage.MinimumSize = new System.Drawing.Size(28, 28);
                    txtMessage.MouseBack = null;
                    txtMessage.MouseState = CCWin.SkinClass.ControlState.Normal;
                    txtMessage.Multiline = true;
                    txtMessage.NormlBack = null;
                    txtMessage.Padding = new System.Windows.Forms.Padding(5);
                    txtMessage.ReadOnly = false;
                    txtMessage.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
                    txtMessage.Size = new System.Drawing.Size(606, 370);
                    txtMessage.AutoScroll = true;
                    txtMessage.Text =string.Format("{0}-开始启动\n", DateTime.Now);
                    this._evs.Add(ev.Key, txtMessage);

                    page.Controls.Add(txtMessage);

                    var btn = new Button();
                    btn.Click += Single_Click;
                    btn.Text = "立即执行";
                    btn.Name = ev.Key;
                    btn.Location = new System.Drawing.Point(0, 380);
                    page.Controls.Add(btn);

                    var lbl = new Label();
                    lbl.AutoSize = true;
                    lbl.Location = new System.Drawing.Point(0, 410);
                    lbl.Size = new System.Drawing.Size(41, 12);
                    lbl.Text = "";

                    //lbl.Text = string.Format("下次执行时间:{0}", this.LoadNextCompleted(ev.Key, ev.TimeOfDay, ev.Minutes));

                    new Thread(() =>
                    {
                        while (true)
                        {
                            try
                            {
                                TimeSpan t = this.LoadNextCompleted(ev.Key, ev.TimeOfDay, ev.Minutes).Subtract(DateTime.Now);

                                //var log_content = this.LoadLog(ev.Key);
                                //if (log_content.IsNotNullOrEmpty())
                                //{
                                //    txtMessage.BeginInvoke(new MethodInvoker(() => txtMessage.SkinTxt.AppendText(log_content)));
                                //    this.EmptyLog(ev.Key);
                                //}


                                txtMessage.BeginInvoke(new MethodInvoker(() => txtMessage.SkinTxt.Text = this.LoadLog(ev.Key)));
                                txtMessage.BeginInvoke(new MethodInvoker(() => txtMessage.SkinTxt.Focus()));
                                txtMessage.BeginInvoke(new MethodInvoker(() => txtMessage.SkinTxt.Select(txtMessage.SkinTxt.TextLength, 0)));//光标定位到文本最后
                                txtMessage.BeginInvoke(new MethodInvoker(() => txtMessage.SkinTxt.ScrollToCaret()));

                                lbl.BeginInvoke(new MethodInvoker(() =>
                                lbl.Text = string.Format("下次执行时间:{0}，剩余:{1}天 {2} 小时 {3} 分 {4} 秒", this.LoadNextCompleted(ev.Key, ev.TimeOfDay, ev.Minutes), t.Days,t.Hours, t.Minutes, t.Seconds)
                            ));
                            }
                            catch { }
                            Thread.Sleep(1000);
                        }
                    })
                    { IsBackground = true }.Start();


                    page.Controls.Add(lbl);

                    tabMonitor.Controls.Add(page);

                    i++;
                }
            }
        }

        /// <summary>
        /// 加载日志文件
        /// </summary>
        private string LoadLog(string key)
        {
            try
            {
                string path = string.Format("{0}log/" + key + ".log", AppDomain.CurrentDomain.BaseDirectory);
                if (!WebTimer.Common.FileOperate.IsExist(path, WebTimer.Common.FileOperate.FsoMethod.File))
                    WebTimer.Common.FileOperate.Create(path, WebTimer.Common.FileOperate.FsoMethod.File);

                return WebTimer.Common.FileOperate.ReadFile(path);
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }

        /// <summary>
        /// 清空日志文件
        /// </summary>
        private void EmptyLog(string key)
        {
            string path = string.Format("{0}log/" + key + ".log", AppDomain.CurrentDomain.BaseDirectory);
            if (!WebTimer.Common.FileOperate.IsExist(path, WebTimer.Common.FileOperate.FsoMethod.File))
                WebTimer.Common.FileOperate.Create(path, WebTimer.Common.FileOperate.FsoMethod.File);

            EventLogs log = new EventLogs();
            log.LogFileName = path;

            log.WriteEmptyLog();
        }


        /// <summary>
        /// 获取下次执行的时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeOfDay"></param>
        /// <param name="minutes"></param>
        /// <returns></returns>
        private DateTime LoadNextCompleted(string key,int timeOfDay,int minutes)
        {
            var lastCompleted = new WebTimer.Common.Func().GetLastExecuteScheduledEventDateTime(key, Environment.MachineName);
            var thisCompleted = DateTime.Now;
            if (timeOfDay > -1)
            {
                DateTime dtNow = DateTime.Now.AddDays(1);
                DateTime dtCompare = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day);
                thisCompleted = dtCompare.AddMinutes(timeOfDay);
            }
            else
            {
                thisCompleted = lastCompleted.AddMinutes(minutes);
            }

            return thisCompleted;
        }


        /// <summary>
        /// 线程工作
        /// </summary>
        /// <param name="sender"></param>
        private void ScheduledEventWorkCallback(object sender)
        {
            try
            {
                if (ScheduleConfigs.GetConfig().Enabled)
                {
                    EventManager.Execute();
                }
            }
            catch (Exception e)
            {
                new EventLogs().LogFileName= string.Format("{0}log/error.log", AppDomain.CurrentDomain.BaseDirectory);

                new EventLogs().WriteFailedLog(e.ToString());
            }
        }

        private void btnEmpty_Click(object sender, EventArgs e)
        {

        }

        //定义与方法同签名的委托  
        private delegate WebTimer.Config.Event Execute(WebTimer.Config.Event ev);

        //回调方法(异步完成时，执行的方法，此方法只有IAsyncResult一个参数，但是该参数几乎万能，可以传递Object)  
        private void CallBackMethod(IAsyncResult ar)
        {
            Execute dn = (Execute)ar.AsyncState;

            WebTimer.Config.Event ev=dn.EndInvoke(ar);//一定要EndInvoke，否则你的下场很惨  
            ScheduledEvents.Event.SetLastExecuteScheduledEventDateTime(ev.Key, Environment.MachineName, DateTime.Now);
        }

        //要进行异步的方法  
        private WebTimer.Config.Event ExecuteSingle(WebTimer.Config.Event ev)
        {
           ((ScheduledEvents.IEvent)Activator.CreateInstance(Type.GetType(ev.ScheduleType))).Execute(this);
            return ev;
        }

        /// <summary>
        /// 单个执行任务事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Single_Click(object sender, EventArgs e)
        {
            var key = (sender as Button).Name;
            WebTimer.Config.Event[] events = ScheduleConfigs.GetConfig().Events;
            foreach (WebTimer.Config.Event ev in events)
            {
                if (ev.Key == key)
                {
                    this.notifyIcon.ShowBalloonTip(5000, "提示", "开始执行"+ ev.Key, ToolTipIcon.Info);

                    //((ScheduledEvents.IEvent)Activator.CreateInstance(Type.GetType(ev.ScheduleType))).Execute(this);
                    //ScheduledEvents.Event.SetLastExecuteScheduledEventDateTime(ev.Key, Environment.MachineName, DateTime.Now);
                    //实例化委托并初赋值  
                    Execute dn = new Execute(ExecuteSingle);
                    //实例化回调函数，把AsyncCallback看成是Delegate就懂了，实际上AsyncCallback是一种特殊的Delegate  
                    AsyncCallback acb = new AsyncCallback(CallBackMethod);
                    //异步开始   
                    //如果参数acb换成null则表示没有回调方法   
                    //最后一个参数dn的地方，可以换成任意对象，该对象可以被回调方法从参数中获取出来，写成null也可以。  
                    //参数dn相当于该线程的ID，如果有多个异步线程，可以都是null，但是绝对不能一样，不能是同一个object，否则异常   
                    IAsyncResult iar = dn.BeginInvoke(ev, acb, dn);

                    break;
                }
            }
        }

        private void FormMain_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)  //判断是否最小化
            {
                this.ShowInTaskbar = false;  //不显示在系统任务栏
                notifyIcon.Visible = true;  //托盘图标可见
                notifyIcon.Text = string.Format("正在运行{0}个监控程序", tabMonitor.TabCount);
            }
        }

        private void notifyIcon_DoubleClick(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.ShowInTaskbar = true;  //显示在系统任务栏
                this.WindowState = FormWindowState.Normal;  //还原窗体
            }

        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            //注意判断关闭事件Reason来源于窗体按钮，否则用菜单退出时无法退出!
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;    //取消"关闭窗口"事件
                this.WindowState = FormWindowState.Minimized;    //使关闭时窗口向右下角缩小的效果
                notifyIcon.Visible = true;
                this.notifyIcon.ShowBalloonTip(5000, "提示", "监控已经最小化至托盘运行！", ToolTipIcon.Info);

                return;
            }
            
        }

        private void 显示ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Normal;
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("是否确认退出程序？", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                // 关闭所有的线程
                this.Dispose();
                this.Close();
            }
        }

        
        private void FormMain_Load(object sender, EventArgs e)
        {

        }
    }
}
